package javawdw.picture.codec;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

import javawdw.picture.api.PictureCodec;
import javawdw.picture.core.Frame;
import javawdw.picture.exception.DecodeException;
import javawdw.picture.exception.EncodeException;

import javax.imageio.ImageIO;

@SuppressWarnings("unchecked")
public class FrameCodec implements PictureCodec<Frame> {
	/**
	 * 将给定注入流解码成Frame
	 * 
	 * @param inputStream
	 *            给定输入流
	 * @return 解码得到的Frame
	 * @throws IOException
	 *             输入流读取失败
	 * @throws DecodeException
	 *             解码失败
	 */
	public Frame decode(InputStream inputStream) throws IOException,
			DecodeException {
		try {
			Class<Frame> c = Frame.class;
			Constructor<Frame> frameCons = c.getDeclaredConstructor();
			frameCons.setAccessible(true);
			Frame frame = frameCons.newInstance();
			BufferedImage image = ImageIO.read(inputStream);
			Field field = c.getDeclaredField("image");
			field.setAccessible(true);
			field.set(frame, image);
			return frame;
		} catch (IOException e) {
			throw e;
		} catch (Exception e) {
			throw new DecodeException();
		}
	}

	/**
	 * 将给定帧图片以写入输出流
	 * 
	 * @param picture
	 *            给定帧图片
	 * @param outputStream
	 *            给定输出流
	 * @throws IOException
	 *             写入输出流异常
	 * @throws EncodeException
	 *             编码失败
	 */
	public void encode(Frame picture, OutputStream outputStream)
			throws IOException, EncodeException {
		try {
			Class<Frame> c = (Class<Frame>) picture.getClass();
			Field field = c.getDeclaredField("image");
			field.setAccessible(true);
			BufferedImage image = (BufferedImage) field.get(picture);
			ImageIO.write(image, "PNG", outputStream);
		} catch (IOException e) {
			throw e;
		} catch (Exception e) {
			throw new EncodeException();
		}
	}

	/**
	 * 获得给定Frame编码后大小
	 * 
	 * @param picture
	 *            给定帧图片
	 * @return 返回图片大小
	 */
	public long getByteSize(Frame picture) throws EncodeException {
		ByteArrayOutputStream byteStream = null;
		try {
			byteStream = new ByteArrayOutputStream();
			this.encode(picture, byteStream);
		} catch (IOException e) {
		} finally {
			try {
				byteStream.close();
			} catch (Exception e) {
			}
		}
		return byteStream.size();
	}
}